package com.geoai.uimap.core.amap

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.os.Bundle
import android.view.View
import com.amap.api.location.AMapLocation
import com.amap.api.location.AMapLocationClient
import com.amap.api.location.AMapLocationClientOption
import com.amap.api.location.AMapLocationListener
import com.amap.api.maps.AMap
import com.amap.api.maps.AMapOptions.LOGO_POSITION_BOTTOM_LEFT
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.LocationSource
import com.amap.api.maps.TextureMapView
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.CustomMapStyleOptions
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MyLocationStyle
import com.geoai.basiclib.utils.log.MyLogUtils
import com.geoai.uimap.api.GEOMapListener
import com.geoai.uimap.api.IGEOMap
import com.geoai.uimap.api.IGEOMapCamera
import com.geoai.uimap.api.IGEOMapOverlayManager
import com.geoai.uimap.api.IGEOMapProjection
import com.geoai.uimap.api.IGEOMapSettings
import com.geoai.uimap.config.MapType
import com.geoai.uimap.core.geomap.GEOMapCustomMapStyleOptions
import com.geoai.uimap.core.geomap.GEOMapSettingsImpl
import com.geoai.uimap.core.geomap.bean.GEOMapCameraPosition
import com.geoai.uimap.model.GEOLatLng
import com.geoai.uimap.model.GEOMapException
import com.geoai.uimap.utils.getAMap
import com.geoai.uimap.utils.toGEOLatLng

class GDMap(private val context: Context) : IGEOMap, LocationSource, AMapLocationListener {

    private var mapView: TextureMapView? = null
    private var mapCamera: GDMapCamera? = null
    private var mapProjection: GDMapProjection? = null
    private var mapOverlayManager: GDMapOverlayManager? = null

    //定位
    private var mlocationClient: AMapLocationClient? = null
    private var mLocationOption: AMapLocationClientOption? = null
    private var mListener: LocationSource.OnLocationChangedListener? = null

    //手机定位点
    private var mLocationLatLng: LatLng? = null

    private var mapType: Int = MapType.MAP_TYPE_SATELLITE

    private var isFirstLocation = true

    private var mapLoaded = false

    //地图加载
    private var mLoaderListener: GEOMapListener.OnMapLoadedListener? = null

    //地图移动
    private var mOnCameraChangeListener: GEOMapListener.OnCameraChangeListener? = null

    //地图点击
    private var mOnMapClickListener: GEOMapListener.OnMapClickListener? = null

    //地图点击
    private var mOnMapLongClickListener: GEOMapListener.OnMapLongClickListener? = null

    //地图缓存清除
    private var mOnCacheRemoveListener: GEOMapListener.OnCacheRemoveListener? = null

    //地图Marker点击
    private var mOnMarkerClickListener: GEOMapListener.OnMarkerClickListener? = null

    private var mOnMapTouchListenerList = mutableListOf<GEOMapListener.OnMapTouchListener>()

    // 设置是否是否原始高德坐标
    var useOriginCorrdinate: Boolean = false
    private fun getLatLng(latLng: LatLng?) = if (useOriginCorrdinate) latLng?.let {
        GEOLatLng(it.latitude, it.longitude)
    } else latLng?.toGEOLatLng()

    private var mUiSettings: IGEOMapSettings? = null
    fun init() {
        mapView = TextureMapView(context)
        mapCamera = GDMapCamera(this)
        mapProjection = GDMapProjection(this)
        mapOverlayManager = GDMapOverlayManager(this)
        mapView?.map?.let {
            initMap(it)
            setMapType(mapType)
            initListener(it)
        }
    }


    private fun initListener(it: AMap) {
        it.setOnMapLoadedListener {
            mLoaderListener?.onMapLoaded()
            mapLoaded = true
        }

        it.setOnCameraChangeListener(object : AMap.OnCameraChangeListener {
            override fun onCameraChange(p0: CameraPosition?) {
                val geoMapCameraPosition = GEOMapCameraPosition()
                geoMapCameraPosition.bearing = p0?.bearing ?: 0f
                geoMapCameraPosition.zoom = p0?.bearing ?: 0f
                geoMapCameraPosition.target = getLatLng(p0?.target)
                mOnCameraChangeListener?.onCameraChange(geoMapCameraPosition)
            }

            override fun onCameraChangeFinish(p0: CameraPosition?) {
                val geoMapCameraPosition = GEOMapCameraPosition()
                geoMapCameraPosition.bearing = p0?.bearing ?: 0f
                geoMapCameraPosition.zoom = p0?.bearing ?: 0f
                geoMapCameraPosition.target = getLatLng(p0?.target)
                mOnCameraChangeListener?.onCameraChangeFinish(geoMapCameraPosition)
            }
        })

        it.setOnMapClickListener { latLng ->
            getLatLng(latLng)?.let { it1 -> mOnMapClickListener?.onMapClick(it1) }
        }

        it.setOnMapLongClickListener { latLng ->
            getLatLng(latLng)?.let { it1 -> mOnMapLongClickListener?.onMapLongClick(it1) }
        }

        it.setOnMarkerClickListener {
            mOnMarkerClickListener?.onMarkerClick(it.id)
            true
        }



        it.addOnMapTouchListener { event ->
            MyLogUtils.d("event----$event")
            mOnMapTouchListenerList.forEach {
                it.onTouch(event)
            }
        }
    }

    override fun onCreate(bundle: Bundle?, mapType: Int) {
//        Log.d(TAG,"onCreate()")
        init()
        mapView?.onCreate(bundle)
        this.mapType = mapType
        setMapType(mapType)
    }

    override fun onResume() {
//        Log.d(TAG,"onResume()")
        mapView?.onResume()
    }

    override fun onPause() {
//        Log.d(TAG,"onPause()")
        mapView?.onPause()
    }

    override fun onStart() {

    }

    override fun onStop() {

    }

    override fun onDestroy() {
//        Log.d(TAG,"onDestroy()")
//        deactivate()
        mapOverlayManager?.onDestroy()
        mapView?.onDestroy()
    }

    override fun getContext(): Context {
        return context
    }

    override fun getMapView(): View {
        return mapView ?: throw GEOMapException(0x1002, "init first")
    }

    override fun getMapCamera(): IGEOMapCamera {
        return mapCamera ?: throw GEOMapException(0x1002, "init first")
    }

    override fun getMapOverlayManager(): IGEOMapOverlayManager {
        return mapOverlayManager!!
    }

    override fun getMapProjection(): IGEOMapProjection {
        return mapProjection ?: throw GEOMapException(0x1002, "init first")
    }

    override fun setMapType(type: Int) {
        mapType = type
        mapView?.map?.let {
            it.mapType = type
            when (type) {
                MapType.MAP_TYPE_NORMAL -> {
                    it.mapType = AMap.MAP_TYPE_NORMAL
                    it.showMapText(true)
                }
                MapType.MAP_TYPE_SATELLITE -> {
                    it.mapType = AMap.MAP_TYPE_SATELLITE
                    it.showMapText(false)
                }

            }
        }
    }

    override fun showHdLayer(show: Boolean) {

    }

    override fun getMapType(): Int {
        return mapType
    }

    override fun isLoaded(): Boolean {
        return mapLoaded
    }

    override fun getMapUiSettings(): IGEOMapSettings? {
        if (mUiSettings == null) {
            mUiSettings = GEOMapSettingsImpl(this)
        }
        return mUiSettings
    }

    override fun setCustomMapStyle(options: GEOMapCustomMapStyleOptions) {
        mapView?.let {
            it.map?.let { amap ->
                amap.setCustomMapStyle(CustomMapStyleOptions().setEnable(options.mEnable)
                        .setStyleData(options.styleData)
                        .setStyleExtraData(options.styleExtraData))
            }
        }
    }

    private fun initMap(aMap: AMap) {
        aMap.uiSettings.isZoomControlsEnabled = false
        aMap.uiSettings.isRotateGesturesEnabled = false
        aMap.uiSettings.isScaleControlsEnabled = false
        aMap.uiSettings.isTiltGesturesEnabled = false
        aMap.uiSettings.logoPosition = LOGO_POSITION_BOTTOM_LEFT
        aMap.uiSettings.setLogoLeftMargin(-1000)
        aMap.uiSettings.setLogoBottomMargin(-1000)
//        aMap.mapType = MapConfig.MAP_TYPE_SATELLITE
        //隐藏底层文字标注
        aMap.showMapText(false)
    }


    override fun initMapLocation(locationIcon: Int, isMyLocationEnabled: Boolean) {
        mapView?.map?.let {
//            Log.d(TAG,"initMapLocation（）mapView?.map=${mapView?.map}")
            isFirstLocation = isMyLocationEnabled
            it.setLocationSource(this) // 设置定位监听
            it.uiSettings.isMyLocationButtonEnabled = false // 设置默认定位按钮是否显示
            it.isMyLocationEnabled = true // 设置为true表示显示定位层并可触发定位，false表示隐藏定位层并不可触发定位，默认是false

            //设置定位风格
            val locationStyle = MyLocationStyle()
            locationStyle.strokeColor(Color.TRANSPARENT)
            locationStyle.radiusFillColor(Color.TRANSPARENT)
            locationStyle.interval(1000)
            locationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(locationIcon))
            locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
            it.myLocationStyle = locationStyle
        }
    }

    override fun deactivate() {
//        Log.d(TAG,"deactivate（）listener=$mListener")
        mListener = null
        if (mlocationClient != null) {
            mlocationClient!!.stopLocation()
            mlocationClient!!.onDestroy()
        }
        mlocationClient = null
    }

    override fun activate(listener: LocationSource.OnLocationChangedListener?) {
//        Log.d(TAG,"activate（）listener=$listener")
        mListener = listener
        if (mlocationClient == null) {
            mlocationClient = AMapLocationClient(context)
            mLocationOption = AMapLocationClientOption()
            //设置定位监听
            mlocationClient!!.setLocationListener(this)
            //设置连续定位
            mLocationOption!!.isOnceLocation = false
            //设置为高精度定位模式
            mLocationOption!!.locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy
            mLocationOption!!.interval = 1000
            //设置定位参数
            mlocationClient!!.setLocationOption(mLocationOption)
            // 此方法为每隔固定时间会发起一次定位请求，为了减少电量消耗或网络流量消耗，
            // 注意设置合适的定位时间的间隔（最小间隔支持为2000ms），并且在合适时间调用stopLocation()方法来取消定位请求
            // 在定位结束后，在合适的生命周期调用onDestroy()方法
            // 在单次定位情况下，定位无论成功与否，都无需调用stopLocation()方法移除请求，定位sdk内部会移除
            mlocationClient!!.startLocation()
        }
    }


    override fun onLocationChanged(amapLocation: AMapLocation?) {
//        Log.d(TAG, "mListener: $mListener, amapLocation: $amapLocation, ")
        if (mListener != null && amapLocation != null) {
            if (amapLocation.errorCode == 0) {
                mListener!!.onLocationChanged(amapLocation)
                mLocationLatLng = LatLng(amapLocation.latitude, amapLocation.longitude)
                if (isFirstLocation) {
                    isFirstLocation = false
                    mapView?.map?.moveCamera(CameraUpdateFactory.newLatLngZoom(mLocationLatLng, 16f))
                }
            } else {
                val errText = "定位失败," + amapLocation.errorCode + ": " + amapLocation.errorInfo
            }
        }
    }

    override fun moveToLocation() {
//        Log.d(TAG, "moveToLocation() mapView?.map=${mapView?.map}, mLocationLatLng=${mLocationLatLng}")
        if (mLocationLatLng != null) {
            mapView?.map?.moveCamera(CameraUpdateFactory.newLatLngZoom(mLocationLatLng, 16f))
        }
    }

    override fun removeCache(listener: GEOMapListener.OnCacheRemoveListener) {
        mOnCacheRemoveListener = listener
        if (mapView?.map != null) {
            mapView?.map?.removecache {
                mOnCacheRemoveListener?.onRemoveCacheFinish(it)
            }
        } else {
            mOnCacheRemoveListener?.onRemoveCacheFinish(true)
        }
    }

    override fun setOnMapLoadedListener(listener: GEOMapListener.OnMapLoadedListener) {
        mLoaderListener = listener
    }

    override fun setOnMapClickListener(listener: GEOMapListener.OnMapClickListener) {
        mOnMapClickListener = listener
    }

    override fun setOnMapLongClickListener(listener: GEOMapListener.OnMapLongClickListener) {
        mOnMapLongClickListener = listener
    }

    override fun setOnCameraChangeListener(listener: GEOMapListener.OnCameraChangeListener) {
        mOnCameraChangeListener = listener
    }

    override fun addOnMapTouchListener(listener: GEOMapListener.OnMapTouchListener) {
        mOnMapTouchListenerList.add(listener)
    }

    override fun removeOnMapTouchListener(listener: GEOMapListener.OnMapTouchListener) {
        mOnMapTouchListenerList.remove(listener)
    }

    override fun setOnMarkerClickListener(listener: GEOMapListener.OnMarkerClickListener) {
        mOnMarkerClickListener = listener
    }

    override fun getMapScreenShot(function: (Bitmap?) -> Unit) {
        getAMap()?.getMapScreenShot(object : AMap.OnMapScreenShotListener {
            override fun onMapScreenShot(p0: Bitmap?) {

            }

            override fun onMapScreenShot(p0: Bitmap?, p1: Int) {
                function.invoke(p0)
            }
        })
    }

    override fun setInfoWindowAdapter(listener: GEOMapListener.InfoWindowAdapter) {
        mapView?.map?.setInfoWindowAdapter(object : AMap.InfoWindowAdapter {
            override fun getInfoWindow(p0: Marker?): View? {
                return listener.getInfoWindow(p0?.id ?: "")
            }

            override fun getInfoContents(p0: Marker?): View? {
                return listener.getInfoContents(p0?.id ?: "")
            }
        })
    }
}